package com.ele.server.dao;

import org.dozer.DozerBeanMapper;
import org.dozer.Mapper;

import javax.persistence.EntityManager;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

public class GenericDAO<T> {
    protected EntityManager em = Persistence.createEntityManagerFactory("persistenceUnit1").createEntityManager();
    protected Class clazz;
    protected Mapper mapper = new DozerBeanMapper();

    public GenericDAO(Class clazz) {
        this.clazz = clazz;
    }

    public T insert(T entity) {
        em.getTransaction().begin();
        em.persist(entity);
        em.getTransaction().commit();

        return serialize(entity);
    }

    public T update(T entity) {
        em.getTransaction().begin();
        em.merge(entity);
        em.getTransaction().commit();

        return serialize(entity);
    }

    public T get(long id) {
        T entity = (T) em.find(clazz, id);
        return serialize(entity);
    }

    public void remove(long id) {
        T entity = get(id);
        if (entity != null) {
            em.getTransaction().begin();
            em.remove(entity);
            em.getTransaction().commit();
        }
    }

    public void remove(Set<Long> ids) {
        if (ids != null && !ids.isEmpty()) {

            StringBuilder sb = new StringBuilder();
            for (Long id : ids) {
                sb.append(",").append(id);
            }
            sb.replace(0, 1, "");

            em.getTransaction().begin();
            String s = String.format("DELETE FROM " + clazz.getSimpleName() + " e WHERE e.id IN ( %s )", sb);
            int deletedCount = em.createQuery(s).executeUpdate();
            em.getTransaction().commit();
        }
    }

    public List<T> list() {
        List<T> list = em.createQuery("SELECT e FROM " + clazz.getSimpleName() + " e").getResultList();
        return serialize(list);
    }

    protected <T> List<T> serialize(Collection<T> list) {
        ArrayList<T> dtoList = new ArrayList<T>();
        for (T a : list) {
            T dto = null;
            if (a != null) {
                dto = (T) mapper.map(a, a.getClass());
            }
            dtoList.add(dto);
        }
        return dtoList;
    }

    protected <T> T serialize(T entity) {
        T dto = null;
        if (entity != null) {
            dto = (T) mapper.map(entity, entity.getClass());
        }

        return dto;
    }

    public List<T> list(Set<Long> ids) {
        List<T> list = null;
        if (ids != null && !ids.isEmpty()) {

            StringBuilder sb = new StringBuilder();
            for (Long id : ids) {
                sb.append(",").append(id);
            }
            sb.replace(0, 1, "");

            String s = String.format("SELECT e FROM " + clazz.getSimpleName() + " e WHERE e.id IN ( %s )", sb);
            list = em.createQuery(s).getResultList();
        }

        return serialize(list);
    }
}

